//
// Created by momolove on 22-12-2.
//

#ifndef UNIX_EXP_CFCLIENT_H
#define UNIX_EXP_CFCLIENT_H

#include <sys/socket.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>

#include "common.h"

#define ENABLE_PROGRESS_BAR

enum EXIT_STATUS {
    FCLIENT_SUCCESS = 0,
    ERR_FCLIENT_ARGUMENT_INVALID = 2,
    ERR_FCLIENT_ARGUMENT_MISSING = 3,
    ERR_FCLIENT_PORT_INVALID = 4,
    ERR_FCLIENT_CONNECTION_FAILED = 11,
    ERR_FCLIENT_ADDRESS_INVALID = 12,
    ERR_FCLIENT_FILENAME_INVALID = 13,
    ERR_FCLIENT_MKDIR_FAILED = 14,
    ERR_FCLIENT_FILE_NOT_AVAILABLE = 21,
    ERR_FCLIENT_INTERNAL_ERROR = 101,
};

const int ACTION_LIST = 0b01;
const int ACTION_DOWNLOAD = 0b10;

const struct option long_options_client[] = {
        {"list", no_argument, NULL, 'l'},
        {"server", required_argument, NULL, 's'},
        {"port", required_argument, NULL, 'p'},
        {"dl", required_argument, NULL, 'd'},
        {"output", required_argument, NULL, 'o'},
        {"help", no_argument, NULL, 'h'},
        {0, 0, 0, 0}
};
const char *short_options_client = "-ls:p:d:o:h";

struct fclient_arguments_t {
    int action;
    char *server;
    int port;
    char *download;
    char *output;
} options = { ACTION_LIST, "localhost", 12345, "" };

#define MAX_RETRY 64
#define BUF_SIZE 128

int socket_fd, output_fd;
char buf[BUF_SIZE];     // recv buffer

int main(int argc, char *argv[]);

/**
 * Print the help message in stderr and exit with -1.
 * @param arg0 (char*) a string to be displayed as the program name, normally it should be argv[0].
 */
void print_help_and_exit(const char *arg0);

/**
 * Parse arguments provided in command line, starting with argv[1].
 * @param argc (int) number of arguments, should be argc of main
 * @param argv (char**) array of arguments, should be argv of main
 */
void parse_args(int argc, char *argv[]);

void do_fclient();

void connect_to_server();

int connect_to_server_impl(struct sockaddr *addr, socklen_t addr_len);

void list_file();

void download_file();

int makedirs(char *path);

void err_cleanup();

#endif // UNIX_EXP_CFCLIENT_H
